package com.yilizhiyou.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yilizhiyou.common.Result;
import com.yilizhiyou.dto.UserLoginDTO;
import com.yilizhiyou.dto.UserRegisterDTO;
import com.yilizhiyou.entity.User;
import com.yilizhiyou.mapper.UserMapper;
import com.yilizhiyou.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 用户服务实现类
 * 
 * @author 伊犁智游开发团队
 * @since 1.0.0
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
    private final UserMapper userMapper;
    private final RedisTemplate<String, Object> redisTemplate;

    public UserServiceImpl(UserMapper userMapper, RedisTemplate<String, Object> redisTemplate) {
        this.userMapper = userMapper;
        this.redisTemplate = redisTemplate;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> register(UserRegisterDTO registerDTO) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 验证密码确认
            if (!registerDTO.getPassword().equals(registerDTO.getConfirmPassword())) {
                result.put("success", false);
                result.put("message", "两次输入的密码不一致");
                return result;
            }

            // 验证用户协议
            if (!registerDTO.getAgreeTerms()) {
                result.put("success", false);
                result.put("message", "请同意用户协议");
                return result;
            }

            // 检查用户名是否已存在
            if (findByUsername(registerDTO.getUsername()) != null) {
                result.put("success", false);
                result.put("message", "用户名已存在");
                return result;
            }

            // 检查手机号是否已存在
            if (StrUtil.isNotBlank(registerDTO.getPhone()) && findByPhone(registerDTO.getPhone()) != null) {
                result.put("success", false);
                result.put("message", "手机号已被注册");
                return result;
            }

            // 检查邮箱是否已存在
            if (StrUtil.isNotBlank(registerDTO.getEmail()) && findByEmail(registerDTO.getEmail()) != null) {
                result.put("success", false);
                result.put("message", "邮箱已被注册");
                return result;
            }

            // 创建用户
            User user = new User();
            user.setUsername(registerDTO.getUsername());
            user.setPassword(BCrypt.hashpw(registerDTO.getPassword(), BCrypt.gensalt()));
            user.setNickname(StrUtil.isNotBlank(registerDTO.getNickname()) ? registerDTO.getNickname() : registerDTO.getUsername());
            user.setPhone(registerDTO.getPhone());
            user.setEmail(registerDTO.getEmail());
            user.setStatus(1);
            user.setUserType(1);
            user.setPoints(0);
            user.setMemberLevel(0);
            user.setCreateBy("system");
            user.setUpdateBy("system");

            boolean saveResult = save(user);
            if (saveResult) {
                result.put("success", true);
                result.put("message", "注册成功");
                result.put("userId", user.getId());
            } else {
                result.put("success", false);
                result.put("message", "注册失败，请重试");
            }

        } catch (Exception e) {
            log.error("用户注册失败", e);
            result.put("success", false);
            result.put("message", "注册失败，系统异常");
        }

        return result;
    }

    @Override
    public Map<String, Object> login(UserLoginDTO loginDTO) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 查询用户
            User user = findByUsername(loginDTO.getUsername());
            if (user == null) {
                result.put("success", false);
                result.put("message", "用户名或密码错误");
                return result;
            }

            // 检查用户状态
            if (user.getStatus() == 0) {
                result.put("success", false);
                result.put("message", "账户已被禁用");
                return result;
            }

            // 验证密码
            if (!BCrypt.checkpw(loginDTO.getPassword(), user.getPassword())) {
                result.put("success", false);
                result.put("message", "用户名或密码错误");
                return result;
            }

            // 生成JWT Token（这里简化处理，实际应该使用JWT工具类）
            String token = generateToken(user);
            
            // 更新最后登录信息
            String currentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            userMapper.updateLastLogin(user.getId(), currentTime, "127.0.0.1");

            // 清除敏感信息
            user.setPassword(null);

            result.put("success", true);
            result.put("message", "登录成功");
            result.put("token", token);
            result.put("user", user);

        } catch (Exception e) {
            log.error("用户登录失败", e);
            result.put("success", false);
            result.put("message", "登录失败，系统异常");
        }

        return result;
    }

    @Override
    public boolean logout(String token) {
        try {
            // 将token加入黑名单（实际应该使用JWT黑名单机制）
            redisTemplate.opsForValue().set("blacklist:" + token, "1", 24, TimeUnit.HOURS);
            return true;
        } catch (Exception e) {
            log.error("用户退出登录失败", e);
            return false;
        }
    }

    @Override
    public User findByUsername(String username) {
        return userMapper.findByUsername(username);
    }

    @Override
    public User findByPhone(String phone) {
        return userMapper.findByPhone(phone);
    }

    @Override
    public User findByEmail(String email) {
        return userMapper.findByEmail(email);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUserInfo(User user) {
        try {
            user.setUpdateBy("user");
            return updateById(user);
        } catch (Exception e) {
            log.error("更新用户信息失败", e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean changePassword(Long userId, String oldPassword, String newPassword) {
        try {
            User user = getById(userId);
            if (user == null) {
                return false;
            }

            // 验证旧密码
            if (!BCrypt.checkpw(oldPassword, user.getPassword())) {
                return false;
            }

            // 更新密码
            user.setPassword(BCrypt.hashpw(newPassword, BCrypt.gensalt()));
            user.setUpdateBy("user");
            return updateById(user);
        } catch (Exception e) {
            log.error("修改密码失败", e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean resetPassword(String phone, String newPassword, String smsCode) {
        try {
            // 验证短信验证码
            if (!verifySmsCode(phone, smsCode, "reset")) {
                return false;
            }

            User user = findByPhone(phone);
            if (user == null) {
                return false;
            }

            // 更新密码
            user.setPassword(BCrypt.hashpw(newPassword, BCrypt.gensalt()));
            user.setUpdateBy("system");
            boolean result = updateById(user);

            // 清除验证码
            if (result) {
                redisTemplate.delete("sms_code:" + phone + ":reset");
            }

            return result;
        } catch (Exception e) {
            log.error("重置密码失败", e);
            return false;
        }
    }

    @Override
    public boolean sendSmsCode(String phone, String type) {
        try {
            // 生成6位数字验证码
            String code = String.format("%06d", (int) (Math.random() * 1000000));
            
            // 存储验证码到Redis，5分钟过期
            String key = "sms_code:" + phone + ":" + type;
            redisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);
            
            // 这里应该调用短信服务发送验证码
            log.info("发送短信验证码: 手机号={}, 验证码={}, 类型={}", phone, code, type);
            
            return true;
        } catch (Exception e) {
            log.error("发送短信验证码失败", e);
            return false;
        }
    }

    @Override
    public boolean verifySmsCode(String phone, String code, String type) {
        try {
            String key = "sms_code:" + phone + ":" + type;
            String storedCode = (String) redisTemplate.opsForValue().get(key);
            return code.equals(storedCode);
        } catch (Exception e) {
            log.error("验证短信验证码失败", e);
            return false;
        }
    }

    /**
     * 生成JWT Token（简化实现）
     */
    private String generateToken(User user) {
        // 这里应该使用JWT工具类生成真正的JWT Token
        // 为了演示，这里返回一个简单的token
        return "token_" + user.getId() + "_" + System.currentTimeMillis();
    }
}
